package org.easy.eao.utils;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.easy.eao.Action;

/**
 * Action 工具类
 * @author Frank
 */
public final class ActionUtils {

	private ActionUtils() {
		throw new IllegalAccessError("该类不允许实例化");
	}

	/**
	 * 以递归方式将数组或集合内的全部单一的对象提取出来
	 * @param source 单一对象，集合或数组
	 * @return 单一对象的集合
	 */
	public static Set<Object> getAllObjects(Object source) {
		Set<Object> objs = new HashSet<Object>();
		if (source == null)
			return objs;
		if (source instanceof Collection<?>) {
			for (Object obj : (Collection<?>) source)
				objs.addAll(getAllObjects(obj));
			return objs;
		}
		if (source.getClass().isArray()) {
			for (Object obj : (Object[]) source)
				objs.addAll(getAllObjects(obj));
			return objs;
		}
		objs.add(source);
		return objs;
	}

	/**
	 * 以递归方式将数组或集合内的全部单一的对象提取出来
	 * @param source 单一对象，集合或数组
	 * @return 单一对象的列表
	 */
	public static List<Object> getAllObjectsAllowDuplicate(Object source) {
		List<Object> objs = new ArrayList<Object>();
		if (source == null)
			return objs;
		if (source instanceof Collection<?>) {
			for (Object obj : (Collection<?>) source)
				objs.addAll(getAllObjectsAllowDuplicate(obj));
			return objs;
		}
		if (source.getClass().isArray()) {
			for (Object obj : (Object[]) source)
				objs.addAll(getAllObjectsAllowDuplicate(obj));
			return objs;
		}
		objs.add(source);
		return objs;
	}

	/** Action Class 与对应的 Annotation 的缓冲 */
	private static Map<Class<Action<?>>, Class<? extends Annotation>> annotationClassCache = 
		new ConcurrentHashMap<Class<Action<?>>, Class<? extends Annotation>>();
	
	/**
	 * 将集合转换为Annotation为键，Class为值的Map
	 * @param actions
	 * @return
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static Map<Class<? extends Annotation>, Class<Action<?>>> toMap(Set<Class<Action<?>>> actions) throws InstantiationException, IllegalAccessException {
		Map<Class<? extends Annotation>, Class<Action<?>>> result = new HashMap<Class<? extends Annotation>, Class<Action<?>>>();
		if (actions == null)
			return result;
		for (Class<Action<?>> clz : actions) {
			result.put(getAnnotionClass(clz), clz);
		}
		return result;
	}

	/**
	 * 获得 Action Class 对应的 Annotation Class
	 * @param clz Action's Class
	 * @return
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static Class<? extends Annotation> getAnnotionClass(Class<Action<? extends Annotation>> clz) throws InstantiationException, IllegalAccessException {
		if (!annotationClassCache.containsKey(clz))
			annotationClassCache.put(clz, clz.newInstance().getAnnotationClass());
		return annotationClassCache.get(clz);
	}

}
